{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Making Chappie\n", "\n", "## Try me\n", " [![Open In Colab](../../_static/colabs_badge.png)](https://colab.research.google.com/github/ffraile/operations-research-notebooks/blob/main/docs/source/CLP/solved/Making%20Chappie%20(Solved%20CBC).ipynb)[![Binder](../../_static/binder_badge.png)](https://mybinder.org/v2/gh/ffraile/operations-research-notebooks/main?labpath=docs%2Fsource%2FCLP%2Fsolved%2FMaking%20Chappie%20(Solved%20CBC).ipynb)\n", "\n", "## Problem definition\n", "The company Tetravaal located in Johannesburg manufactures two types of robots, Model $P_{1}$ and Model $P_{2}$. The production plant is consisted of four different sections: metal machining, plastic moulding, electrical work and assembly. \n", "The metal machining section has a capacity of 7500 units of $P_{1}$ or 6000 units of $P_{2}$ per month. \n", "\n", "Plastic moulding can process 5000 units of $P_{1}$ or 9000 units of $P_{2}$ per month.\n", "\n", "Electrical work can process 6000 units of $P_{1}$ or 7000 units of $P_{2}$ per month.\n", "\n", "In Assembly, there are two assembly lines that work in parallel, one per each robot model.\n", "\n", "The first assembly line can process 4000 units of $P_{1}$ per month\n", "\n", "The second assembly line can process 5000 units of $P_{2}$ per month\n", "\n", "Knowing that the unitary profit of $P_{1}$ is 500€ and that the unitary profit of $P_{2}$ is 600€, and that both robots have a great demand and therefore all manufactured robots are sold, Michelle Bradley, CEO of Tetravaal, asks his engineering team: \n", "\n", "Calculate the number of units of each robot that needs to be manufactured to maximise profit for the company." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Model\n", "We want to maximise the company profits:\n", "\n", "$\\max z = 500x_{1} + 600x_{2}$\n", "\n", "where z represents the profits (€). The decision variables are:\n", "\n", "$x_{1}:$ units of $P_{1}$ per month\n", "$x_{2}:$ units of $P_{2}$ per month\n", "\n", "The objective function is subject to the following constraints:\n", "\n", "$x_{1}/7500+x_{2}/6000 \\leq 1$ Metal machining constraint\n", "\n", "$x_{1}/5000+x_{2}/9000 \\leq 1$ Plastic moulding constraint\n", "\n", "$x_{1}/6000 + x_{2}/7000 \\leq 1$ Electrical work constraint\n", "\n", "$x_{1} \\leq 4000$ First assembly line constraint \n", "\n", "$x_{2} \\leq 5000$ Second assembly line constraint" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Solution using PuLP\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\franc\\PycharmProjects\\operations-research-notebooks\\venv\\Lib\\site-packages\\pulp\\pulp.py:1316: UserWarning: Spaces are not permitted in the name. Converted to '_'\n", " warnings.warn(\"Spaces are not permitted in the name. Converted to '_'\")\n" ] }, { "data": { "text/plain": "'Optimal'" }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "import numpy as np\n", "from IPython.display import display, Markdown\n", "import pulp\n", "\n", "model = pulp.LpProblem(\"Maximising profits for Tetravaal\", pulp.LpMaximize)\n", "\n", "variable_names = ['P1', 'P2']\n", "\n", "variables = pulp.LpVariable.dicts(\"Units per month\",\n", " (i for i in variable_names),\n", " lowBound=0,\n", " cat='Continuous')\n", "\n", "coefficients = [500, 600]\n", "\n", "# Objective function\n", "model += (\n", " pulp.lpSum([\n", " coefficients[i] * variables[variable_names[i]]\n", " for i in range(len(variable_names))])\n", "), \"Profit\"\n", "\n", "\n", "# And the constraints, the Matrix A\n", "A=[[1/7500, 1/6000], #Coefficients of the first constraint\n", " [1/5000, 1/9000], #Coefficients of the second constraint\n", " [1/6000, 1/7000],\n", " [1/4000, 0], #Coefficients of the second constraint\n", " [0, 1/5000]] #Coefficients of the third constraint\n", "\n", "A = A\n", "\n", "# And vector b\n", "b = [1, 1, 1, 1, 1] #limits of the three constraints\n", "\n", "constraint_names = ['Metal machining', 'Plastic moulding', 'Electrical work', 'Assembly 1', 'Assembly 2']\n", "\n", "# Constraints\n", "for i in range(len(A)): \n", " model += pulp.lpSum([\n", " A[i][j] * variables[variable_names[j]] \n", " for j in range(len(variable_names))]) <= b[i] , constraint_names[i]\n", "\n", " # Solve our problem\n", "model.solve()\n", "pulp.LpStatus[model.status]\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": "", "text/markdown": "Total profit is 3654545.43 €" }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": "", "text/markdown": "The following table shows the decision variables: " }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": " Variables Solution Reduced cost\nP1 Units_per_month_P1 2727.2727 0.000000e+00\nP2 Units_per_month_P2 3818.1818 -6.394885e-14", "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
VariablesSolutionReduced cost
P1Units_per_month_P12727.27270.000000e+00
P2Units_per_month_P23818.1818-6.394885e-14
\n
" }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": "", "text/markdown": "The following table shows the constraints: " }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": " Constraint Right Hand Side Slack Shadow Price\n0 Metal_machining 1.0 -0.000000 3272727.30\n1 Plastic_moulding 1.0 0.030303 -0.00\n2 Electrical_work 1.0 -0.000000 381818.18\n3 Assembly_1 1.0 0.318182 -0.00\n4 Assembly_2 1.0 0.236364 -0.00", "text/html": "
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
ConstraintRight Hand SideSlackShadow Price
0Metal_machining1.0-0.0000003272727.30
1Plastic_moulding1.00.030303-0.00
2Electrical_work1.0-0.000000381818.18
3Assembly_11.00.318182-0.00
4Assembly_21.00.236364-0.00
\n
" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "total_profit = pulp.value(model.objective)\n", "display(Markdown(\"Total profit is %0.2f €\"%total_profit))\n", "\n", "display(Markdown(\"The following table shows the decision variables: \"))\n", "var_df = pd.DataFrame.from_dict(variables, orient=\"index\",\n", " columns = [\"Variables\"])\n", "\n", "# First we add the solution. We apply a lambda function to get only two decimals:\n", "var_df[\"Solution\"] = var_df[\"Variables\"].apply(lambda item: item.varValue)\n", "# We do the same for the reduced cost:\n", "var_df[\"Reduced cost\"] = var_df[\"Variables\"].apply(lambda item: item.dj)\n", "\n", "display(var_df)\n", "\n", "\n", "const_dict = dict(model.constraints)\n", "con_df = pd.DataFrame.from_records(list(const_dict.items()), exclude=[\"Expression\"], columns=[\"Constraint\", \"Expression\"])\n", "#Now we add columns for the solution, the slack and shadow price\n", "\n", "con_df[\"Right Hand Side\"] = con_df[\"Constraint\"].apply(lambda item: -const_dict[item].constant)\n", "con_df[\"Slack\"] = con_df[\"Constraint\"].apply(lambda item: const_dict[item].slack)\n", "con_df[\"Shadow Price\"] = con_df[\"Constraint\"].apply(lambda item: const_dict[item].pi)\n", "\n", "\n", "display(Markdown(\"The following table shows the constraints: \"))\n", "display(con_df)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.4" }, "pycharm": { "stem_cell": { "cell_type": "raw", "source": [], "metadata": { "collapsed": false } } } }, "nbformat": 4, "nbformat_minor": 2 }